import * as vscode from 'vscode';
import Parser = require('tree-sitter');
import { ErrorType } from './errorClassifier';
import { TextHelper } from './textHelper';

export interface LSPSuggestion {
  functionInfo?: string;
  hoverInfo?: string;
  signatures?: string[];
  codeActions?: string[];
  completions?: string[];
}

export class LSPSuggester {
  private static readonly MAX_SUGGESTIONS = 3;
  private static readonly MAX_TEXT_LENGTH = 150;

  static async getSuggestions(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode,
    diagnostic: vscode.Diagnostic,
    errorType: ErrorType
  ): Promise<LSPSuggestion> {
    const suggestions: LSPSuggestion = {};

    try {
      // 根据错误类型决定获取哪些建议
      switch (errorType) {
        case ErrorType.FUNCTION_ERROR:
          suggestions.functionInfo = await this.getFunctionInfo(doc, position, errorNode);
          suggestions.signatures = await this.getSignatures(doc, position, errorNode);
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
          break;
          
        case ErrorType.UNDEFINED_ERROR:
        case ErrorType.VARIABLE_ERROR:
          suggestions.completions = await this.getCompletions(doc, position, errorNode);
          suggestions.hoverInfo = await this.getHoverInfo(doc, position, errorNode);
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
          break;
          
        case ErrorType.ATTRIBUTE_ERROR:
        case ErrorType.SPELLING_ERROR:
          // 属性错误和拼写错误特别需要获取相似的建议
          suggestions.completions = await this.getSmartCompletions(doc, position, errorNode);
          suggestions.hoverInfo = await this.getHoverInfo(doc, position, errorNode);
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
          break;
          
        case ErrorType.TYPE_ERROR:
          suggestions.hoverInfo = await this.getHoverInfo(doc, position, errorNode);
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
          break;
          
        case ErrorType.IMPORT_ERROR:
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
          break;
          
        default:
          // 其他类型的错误获取通用建议
          suggestions.hoverInfo = await this.getHoverInfo(doc, position, errorNode);
          suggestions.codeActions = await this.getCodeActions(doc, diagnostic);
      }
    } catch (error) {
      console.log(`获取LSP建议时出错: ${error}`);
    }

    return suggestions;
  }

  private static async getFunctionInfo(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode
  ): Promise<string | undefined> {
    try {
      let functionName = '';
      if (errorNode.type === 'call') {
        const functionNode = errorNode.child(0);
        if (functionNode) {
          functionName = functionNode.text;
        }
      }

      if (functionName) {
        const definitions = await vscode.commands.executeCommand<vscode.Location[]>(
          'vscode.executeDefinitionProvider',
          doc.uri,
          position
        );

        if (definitions && definitions.length > 0) {
          const def = definitions[0];
          const defDoc = await vscode.workspace.openTextDocument(def.uri);
          const defLine = defDoc.lineAt(def.range.start.line).text;
          const fileName = def.uri.fsPath.split('/').pop() || def.uri.fsPath;
          return TextHelper.truncate(
            `${fileName}:${def.range.start.line + 1} - ${defLine.trim()}`,
            this.MAX_TEXT_LENGTH
          );
        }
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static async getHoverInfo(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode
  ): Promise<string | undefined> {
    try {
      const positions = [
        position,
        new vscode.Position(errorNode.startPosition.row, errorNode.startPosition.column),
        new vscode.Position(errorNode.endPosition.row, Math.max(0, errorNode.endPosition.column - 1))
      ];

      for (const pos of positions) {
        const hovers = await vscode.commands.executeCommand<vscode.Hover[]>(
          'vscode.executeHoverProvider',
          doc.uri,
          pos
        );

        if (hovers && hovers.length > 0) {
          const hoverContent = hovers[0].contents
            .map(content => typeof content === 'string' ? content : content.value)
            .join('\n');

          if (hoverContent.trim()) {
            return TextHelper.truncate(hoverContent, this.MAX_TEXT_LENGTH);
          }
        }
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static async getSignatures(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode
  ): Promise<string[] | undefined> {
    try {
      if (this.isFunctionCallNode(errorNode)) {
        const signatureHelp = await vscode.commands.executeCommand<vscode.SignatureHelp>(
          'vscode.executeSignatureHelpProvider',
          doc.uri,
          position
        );

        if (signatureHelp && signatureHelp.signatures.length > 0) {
          return signatureHelp.signatures
            .slice(0, this.MAX_SUGGESTIONS)
            .map(sig => {
              const doc = typeof sig.documentation === 'string' 
                ? sig.documentation 
                : sig.documentation?.value || '';
              const docText = doc ? ` - ${doc}` : '';
              return TextHelper.truncate(`${sig.label}${docText}`, this.MAX_TEXT_LENGTH);
            });
        }
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static async getCodeActions(
    doc: vscode.TextDocument,
    diagnostic: vscode.Diagnostic
  ): Promise<string[] | undefined> {
    try {
      const codeActions = await vscode.commands.executeCommand<vscode.CodeAction[]>(
        'vscode.executeCodeActionProvider',
        doc.uri,
        diagnostic.range
      );

      if (codeActions && codeActions.length > 0) {
        const usefulActions = codeActions
          .filter(action => this.isUsefulCodeAction(action.title))
          .slice(0, this.MAX_SUGGESTIONS)
          .map(action => TextHelper.truncate(action.title, this.MAX_TEXT_LENGTH));

        return usefulActions.length > 0 ? usefulActions : undefined;
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static async getSmartCompletions(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode
  ): Promise<string[] | undefined> {
    try {
      const errorText = errorNode.text.toLowerCase();
      
      // 尝试多个位置获取补全建议
      const positions = [
        position,
        new vscode.Position(errorNode.startPosition.row, errorNode.startPosition.column),
        // 如果是属性访问，尝试在点号后面获取补全
        new vscode.Position(errorNode.startPosition.row, Math.max(0, errorNode.startPosition.column - 1))
      ];

      for (const pos of positions) {
        const completions = await vscode.commands.executeCommand<vscode.CompletionList>(
          'vscode.executeCompletionItemProvider',
          doc.uri,
          pos
        );

        if (completions && completions.items && completions.items.length > 0) {
          // 查找相似的建议
          const similarItems = completions.items
            .map(item => ({
              item,
              similarity: TextHelper.calculateSimilarity(item.label.toString().toLowerCase(), errorText)
            }))
            .filter(({ similarity }) => similarity > 0.3) // 降低相似度阈值
            .sort((a, b) => b.similarity - a.similarity) // 按相似度排序
            .slice(0, this.MAX_SUGGESTIONS)
            .map(({ item, similarity }) => {
              const detail = item.detail ? ` - ${item.detail}` : '';
              const simPercent = Math.round(similarity * 100);
              return TextHelper.truncate(
                `${item.label}${detail} (相似度: ${simPercent}%)`,
                this.MAX_TEXT_LENGTH
              );
            });

          if (similarItems.length > 0) {
            return similarItems;
          }

          // 如果没有找到相似的，返回前几个一般建议
          const generalItems = completions.items
            .slice(0, this.MAX_SUGGESTIONS)
            .map(item => {
              const detail = item.detail ? ` - ${item.detail}` : '';
              return TextHelper.truncate(`${item.label}${detail}`, this.MAX_TEXT_LENGTH);
            });

          if (generalItems.length > 0) {
            return generalItems;
          }
        }
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static async getCompletions(
    doc: vscode.TextDocument,
    position: vscode.Position,
    errorNode: Parser.SyntaxNode
  ): Promise<string[] | undefined> {
    try {
      if (errorNode.type === 'identifier' || errorNode.type === 'attribute') {
        const completions = await vscode.commands.executeCommand<vscode.CompletionList>(
          'vscode.executeCompletionItemProvider',
          doc.uri,
          position
        );

        if (completions && completions.items) {
          const errorText = errorNode.text.toLowerCase();
          let relevantItems = completions.items.filter(item => {
            const label = item.label.toString().toLowerCase();
            return label.includes(errorText) || 
                   TextHelper.calculateSimilarity(label, errorText) > 0.5;
          });

          if (relevantItems.length === 0) {
            relevantItems = completions.items.slice(0, this.MAX_SUGGESTIONS);
          }

          return relevantItems
            .slice(0, this.MAX_SUGGESTIONS)
            .map(item => {
              const detail = item.detail ? ` - ${item.detail}` : '';
              return TextHelper.truncate(`${item.label}${detail}`, this.MAX_TEXT_LENGTH);
            });
        }
      }
    } catch (error) {
      // 忽略错误
    }
    return undefined;
  }

  private static isFunctionCallNode(node: Parser.SyntaxNode): boolean {
    return node.type === 'call_expression' || 
           node.type === 'function_call' ||
           node.parent?.type === 'call_expression' ||
           node.parent?.type === 'function_call';
  }

  private static isUsefulCodeAction(title: string): boolean {
    const uselessPatterns = [
      'type: ignore',
      '提取',
      'extract',
      'disable',
      'suppress'
    ];

    const usefulPatterns = [
      '转换',
      '修复',
      '更正',
      '替换',
      'convert',
      'fix',
      'correct',
      'replace'
    ];

    const titleLower = title.toLowerCase();
    
    // 排除无用的建议
    if (uselessPatterns.some(pattern => titleLower.includes(pattern))) {
      return false;
    }

    // 包含有用的建议
    return usefulPatterns.some(pattern => titleLower.includes(pattern));
  }
}